package com.wut.clock.service.impl;

import com.wut.clock.common.constant.CommentConstant;
import com.wut.clock.common.constant.MessageConstant;
import com.wut.clock.common.service.RedisService;
import com.wut.clock.common.util.RedisKeyUtil;
import com.wut.clock.entity.Message;
import com.wut.clock.event.EventProducer;
import com.wut.clock.service.ILikeService;
import com.wut.clock.util.ShiroUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

/**
 * @author ZYH
 * @unit D9Lab
 * @description 点赞点踩实现类
 * @date 2022/6/10 10:00
 */
@Service
@RequiredArgsConstructor
@SuppressWarnings("unchecked")
public class LikeServiceImpl implements ILikeService {

    private final RedisTemplate redisTemplate;

    private final EventProducer eventProducer;

    @Override
    public void like(Integer entityId, Integer entityType, Integer targetUserId) {
        redisTemplate.execute(new SessionCallback(){
            @Override
            public Object execute(RedisOperations redisOperations) throws DataAccessException {
                // 首先获取到需要进行修改的key
                String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityId, entityType);
                String userLikeKey = RedisKeyUtil.getUserLikeKey(targetUserId);
                // 获得当前用户id
                Integer userId = ShiroUtil.getUserId();
                // 判断当前用户是否已经点过赞了，如果已赞，则再点为取消点赞
                boolean status = getEntityLikeStatus(entityId, entityType);
                // 开启redis的事务
                redisOperations.multi();
                // 开启事务后，在事务中进行redis Key的修改
                if(status){
                    // 点过赞，进行取消点赞操作
                    redisOperations.opsForValue().decrement(userLikeKey);
                    redisOperations.opsForValue().setBit(entityLikeKey,userId,false);
                }else {
                    // 未点赞，进行点赞操作
                    redisOperations.opsForValue().setBit(entityLikeKey,userId,true);
                    redisOperations.opsForValue().increment(userLikeKey);
                    // 发送系统通知
                    Message message = new Message();
                    message.setUserId(targetUserId);
                    message.setFromUserId(userId);
                    message.setTargetId(entityId);
                    message.setTargetType(entityType);
                    message.setType(MessageConstant.Type.LIKE.getCode());
                    eventProducer.fireLikeEvent(message);
                }
                // 操作对象发生改变，我们使用redis的set集合去判断
                if(entityType.equals(CommentConstant.TopicType.ARTICLE.getCode())){
                    String redisKey = RedisKeyUtil.getArticleScore();
                    redisTemplate.opsForSet().add(redisKey,entityId);
                }
                return redisOperations.exec();
            }
        });
    }

    @Override
    public boolean getEntityLikeStatus(Integer entityId, Integer entityType) {
        // 获取实体的key
        String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityId, entityType);
        // 获得当前登录用户的用户id
        Integer userId = ShiroUtil.getUserId();
        Boolean bit = redisTemplate.opsForValue().getBit(entityLikeKey, userId);
        if (bit != null) return bit;
        return false;
    }

    @Override
    public long getEntityLikeCount(Integer entityId, Integer entityType) {
        String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityId, entityType);
        Long size = redisTemplate.opsForValue().size(entityLikeKey);
        if(size == null) return 0;
        return size;
    }

    @Override
    public int getUserLikeCount(Integer userId) {
        String userLikeKey = RedisKeyUtil.getUserLikeKey(userId);
        return (int)redisTemplate.opsForValue().get(userLikeKey);
    }
}
